package com.shawn.datastructure.stack;

public class SampleBrowser {

	public static void main(String[] args) {
		SampleBrowser browser = new SampleBrowser();
		browser.open("http://www.baidu.com");
		browser.open("http://news.baidu.com/");
		browser.open("http://news.baidu.com/ent");
		browser.goBack();
		browser.goBack();
		browser.goForward();
		browser.open("http://www.qq.com");
		browser.goForward();
		browser.goBack();
		browser.goForward();
		browser.goBack();
		browser.goBack();
		browser.goBack();
		browser.goBack();
		browser.checkCurrentPage();
	}

	private String currentPage;
	private LinkedListBasedStack backStack;
	private LinkedListBasedStack forwardStack;

	public SampleBrowser() {
		this.backStack = new LinkedListBasedStack();
		this.forwardStack = new LinkedListBasedStack();
	}

	public void open(String url) {
		if (this.currentPage != null) {
			this.backStack.push(this.currentPage);
			this.forwardStack.clear();
		}
		showUrl(url, "Open");
	}

	public boolean canGoBack() {
		return this.backStack.size() > 0;
	}

	public boolean canGoForward() {
		return this.forwardStack.size() > 0;
	}

	public String goBack() {
		if (this.canGoBack()) {
			this.forwardStack.push(this.currentPage);
			String backUrl = this.backStack.pop();
			showUrl(backUrl, "Back");
			return backUrl;
		}
		System.out.println("* Cannot go back, no pages behind.");
		return null;
	}

	public String goForward() {
		if (this.canGoForward()) {
			this.backStack.push(this.currentPage);
			String forwardUrl = this.forwardStack.pop();
			showUrl(forwardUrl, "Foward");
			return forwardUrl;
		}

		System.out.println("** Cannot go forward, no pages ahead.");
		return null;
	}

	public void checkCurrentPage() {
		System.out.println("Current page is: " + this.currentPage);
	}

	public void showUrl(String url, String prefix) {
		this.currentPage = url;
		System.out.println(prefix + " page == " + url);
	}


	private static class LinkedListBasedStack {

		private Node top;

		private int size;

		static Node createNode(String data, Node next) {
			return new Node(data, next);
		}

		void clear() {
			this.top = null;
			this.size = 0;
		}

		void push(String data) {
			Node node = createNode(data, this.top);
			top = node;
			size++;
		}

		String pop() {
			Node popNode = this.top;
			if (popNode == null) {
				System.out.println("Stack is empty.");
				return null;
			}
			this.top = popNode.next;
			if (this.size > 0) {
				this.size--;
			}
			return popNode.data;
		}

		String getTopData() {
			if (this.top == null) {
				return null;
			}
			return this.top.data;
		}

		int size() {
			return this.size;
		}

		void print() {
			System.out.println("Print stack:");
			Node currentNode = this.top;
			while (currentNode != null) {
				String data = currentNode.getData();
				System.out.print(data + "\t");
				currentNode = currentNode.next;
			}
			System.out.println();
		}

		private static class Node {

			private String data;
			private Node next;

			public Node(String data) {
				this(data, null);
			}

			public Node(String data, Node next) {
				this.data = data;
				this.next = next;
			}

			public void setData(String data) {
				this.data = data;
			}

			public String getData() {
				return this.data;
			}

			public void setNext(Node next) {
				this.next = next;
			}

			public Node getNext() {
				return this.next;
			}
		}

	}

}
